package com.geline.sqlbackup.util;

import com.alibaba.druid.DbType;
import com.geline.sqlbackup.bean.InformationTable;
import com.geline.sqlbackup.bean.SequenceInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.jdbc.SqlRunner;
import org.springframework.jdbc.datasource.DataSourceUtils;

import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: mengx
 * @date: 2021/10/16 18:21
 */
@Slf4j
public class SqlInformationUtils {

    /**
     * 查询表信息
     * @param dataSource
     * @return
     */
    public static List<InformationTable> getInformationTableList(DataSource dataSource) {
        DbType dbType = JdbcDbTypeUtil.getDbTypeOfDruid(dataSource);
        if (dbType == DbType.kingbase) {
            return KingbaseInformationUtil.getInformationTableList(dataSource);
        } else if(dbType == DbType.other){
            return ShenTongInformationUtil.getInformationTableList(dataSource);
        }else {
            return MysqlInformationUtil.getInformationTableList(dataSource);
        }
    }

    /**
     * 查询数据库中所有表名列表
     * @param dataSource
     * @param sql
     * @return
     */
    public static List<InformationTable> selectInformationTablesBySql(DataSource dataSource, String sql){
        Connection connection = null;
        try {
            connection = DataSourceUtils.doGetConnection(dataSource);
            String ipPort = JdbcParseUtils.findIpPortByUrl(connection.getMetaData().getURL());
            log.debug("====>   selectTableNamesBySql connection: {}", ipPort);
            log.debug("====>   Sql: {}", sql);
            List<Map<String, Object>> mapList = new SqlRunner(connection).selectAll(sql);
            List<InformationTable> tableNameList = mapList.stream().map(row -> {
                InformationTable informationTable = new InformationTable();
                informationTable.setTableName((String)row.get("TABLE_NAME"));
                informationTable.setTableComment((String)row.get("TABLE_COMMENT"));
                return informationTable;
            }).collect(Collectors.toList());
            log.debug("<====   Total: {}", tableNameList.size());
            return tableNameList;
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                DataSourceUtils.doReleaseConnection(connection, dataSource);
            } catch (SQLException e) {
                log.error("fail to close connection !!!");
            }
        }
    }

    /**
     * 查询数据库中所有序列列表
     * @param dataSource
     * @param sql
     * @return
     */
    public static List<SequenceInfo> selectInformationSequenceBySql(DataSource dataSource, String sql) {
        Connection connection = null;
        try {
            connection = DataSourceUtils.doGetConnection(dataSource);
            String ipPort = JdbcParseUtils.findIpPortByUrl(connection.getMetaData().getURL());
            log.debug("====>   selectSequenceBySql connection: {}", ipPort);
            log.debug("====>   Sql: {}", sql);
            List<Map<String, Object>> mapList = new SqlRunner(connection).selectAll(sql);

            List<SequenceInfo> sequenceList = mapList.stream().map(row -> {
                SequenceInfo informationSequence = new SequenceInfo();
                informationSequence.setSequenceOwner((String)row.get("SEQUENCE_OWNER"));
                informationSequence.setSequenceName((String)row.get("SEQUENCE_NAME"));
                informationSequence.setMinValue(Integer.parseInt(((BigDecimal)row.get("MIN_VALUE")).toString()));
                informationSequence.setMaxValue(Long.parseLong(((BigDecimal)row.get("MAX_VALUE")).toString()));
                informationSequence.setIncrementBy(Integer.parseInt(((BigDecimal)row.get("INCREMENT_BY")).toString()));
                informationSequence.setCycleFlag((String)row.get("CYCLE_FLAG"));
                informationSequence.setOrderFlag((String)row.get("ORDER_FLAG"));
                informationSequence.setCacheSize(Integer.parseInt(((BigDecimal)row.get("CACHE_SIZE")).toString()));
                informationSequence.setLastNumber(Long.parseLong(((BigDecimal)row.get("LAST_NUMBER")).toString()));
                return informationSequence;
            }).collect(Collectors.toList());
            log.debug("<====   Total: {}", sequenceList.size());
            return sequenceList;
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                DataSourceUtils.doReleaseConnection(connection, dataSource);
            } catch (SQLException e) {
                log.error("fail to close connection !!!");
            }
        }
    }
}
